// src/utils/logger.js
const { createLogger, format, transports } = require('winston');
const { combine, timestamp, printf, colorize, errors } = format;
const DailyRotateFile = require('winston-daily-rotate-file');
const path = require('path');
const util = require('util');
const cls = require('cls-hooked');
const os = require('os');

// 创建异步命名空间（用于请求上下文跟踪）
const logNamespace = cls.createNamespace('logger');
const APP_NAME = process.env.APP_NAME || 'my-app';
const LOG_DIR = process.env.LOG_DIR || path.join(__dirname, '../../logs');

/**
 * 自定义格式化工具
 */
const customFormat = printf(({ level, message, timestamp, stack, ...meta }) => {
  // 获取请求上下文（如果有）
  const context = logNamespace.get('context') || {};
  const requestId = context.requestId || 'SYSTEM';

  // 构建日志文本
  let logText = `[${timestamp}] [${level.toUpperCase()}] [${requestId}] ${message}`;
  
  // 添加堆栈信息（如果是错误）
  if (stack) {
    logText += `\n${stack}`;
  }

  // 添加额外元数据（过滤掉敏感字段）
  if (Object.keys(meta).length > 0) {
    const filteredMeta = filterSensitiveFields(meta);
    logText += `\n${util.inspect(filteredMeta, { depth: 5, colors: false })}`;
  }

  return logText;
});

/**
 * 敏感字段过滤
 */
function filterSensitiveFields(meta) {
  const SENSITIVE_KEYS = ['password', 'token', 'authorization', 'creditCard'];
  const filtered = { ...meta };

  SENSITIVE_KEYS.forEach(key => {
    if (filtered[key]) {
      filtered[key] = '***REDACTED***';
    }
  });

  return filtered;
}

/**
 * 创建日志传输器
 */
function createTransports() {
  const transportList = [
    // 控制台输出（开发环境）
    new transports.Console({
      level: process.env.NODE_ENV === 'production' ? 'info' : 'debug',
      format: combine(
        colorize(),
        customFormat
      )
    }),
    // 每日轮换的错误日志文件
    new DailyRotateFile({
      level: 'error',
      filename: path.join(LOG_DIR, 'error-%DATE%.log'),
      datePattern: 'YYYY-MM-DD',
      zippedArchive: true,
      maxSize: '20m',
      maxFiles: '30d'
    }),
    // 每日轮换的完整日志文件
    new DailyRotateFile({
      filename: path.join(LOG_DIR, 'combined-%DATE%.log'),
      datePattern: 'YYYY-MM-DD',
      zippedArchive: true,
      maxSize: '20m',
      maxFiles: '30d'
    })
  ];

  // 生产环境添加Syslog支持
  if (process.env.ENABLE_SYSLOG === 'true') {
    transportList.push(
      new transports.Syslog({
        host: process.env.SYSLOG_HOST || 'localhost',
        port: process.env.SYSLOG_PORT || 514,
        protocol: process.env.SYSLOG_PROTOCOL || 'udp',
        app_name: APP_NAME,
        format: format.simple()
      })
    );
  }

  return transportList;
}

/**
 * 主日志记录器
 */
const logger = createLogger({
  level: process.env.LOG_LEVEL || 'info',
  defaultMeta: { 
    service: APP_NAME,
    hostname: os.hostname(),
    pid: process.pid 
  },
  format: combine(
    timestamp({ format: 'YYYY-MM-DD HH:mm:ss.SSS' }),
    errors({ stack: true }), // 错误堆栈处理
    format.splat(),         // 支持字符串插值
    customFormat
  ),
  transports: createTransports(),
  exceptionHandlers: [
    new transports.File({ 
      filename: path.join(LOG_DIR, 'exceptions.log') 
    })
  ],
  rejectionHandlers: [
    new transports.File({ 
      filename: path.join(LOG_DIR, 'rejections.log') 
    })
  ]
});

/**
 * 请求上下文绑定中间件
 */
logger.bindRequestContext = (req, res, next) => {
  logNamespace.bindEmitter(req);
  logNamespace.bindEmitter(res);

  logNamespace.run(() => {
    const requestId = req.headers['x-request-id'] || crypto.randomUUID();
    logNamespace.set('context', { 
      requestId,
      method: req.method,
      url: req.originalUrl,
      ip: req.ip
    });

    // 记录请求开始
    logger.info(`Started ${req.method} ${req.originalUrl}`, {
      headers: filterSensitiveFields(req.headers),
      query: req.query,
      body: req.body
    });

    const startTime = Date.now();
    res.on('finish', () => {
      // 记录请求完成
      logger.info(`Completed ${res.statusCode} in ${Date.now() - startTime}ms`, {
        status: res.statusCode,
        contentLength: res.get('content-length'),
        userAgent: req.get('user-agent')
      });
    });

    next();
  });
};

/**
 * 自定义日志方法扩展
 */
logger.api = (message, meta = {}) => {
  logger.info(`[API] ${message}`, meta);
};

logger.db = (query, duration, meta = {}) => {
  logger.debug(`[DB] ${query} (${duration}ms)`, meta);
};

logger.security = (event, meta = {}) => {
  logger.warn(`[SECURITY] ${event}`, meta);
};

module.exports = logger;